home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 07 - 1991 / 07.10 Oct 91 / Window Menubar Source ƒ / wBarMenu.p < prev    next >
Encoding:
Text File  |  1991-07-25  |  39.3 KB  |  1,685 lines  |  [TEXT/PJMM]

  1. { ******************************************************** }
  2. { "wBarMenu.p"                                             }
  3. {                                                          }
  4. { by:                                                      }
  5. {      James Matthews                                      }
  6. {         < MacTutor -- Nov 88 >                           }
  7. {                                                          }
  8. { with color + hierarchial Menu support                    }
  9. { and other nifty additions by:                            }
  10. {      John A. Love, III                                   }
  11. {         [ Washington Apple Pi Users' Group]              }
  12. {                                                          }
  13. { using Symantec's "THINK Lightspeed Pascal", v 3.02       }
  14. {                                                          }
  15. { ******************************************************** }
  16.  
  17.  
  18.  
  19.  
  20. PROGRAM wBarMenu;
  21.  
  22. {$I-}
  23.  
  24.     USES
  25.         Types, Memory, OSUtils, Quickdraw, Events, Files, AppleTalk, PPCToolbox, Processes, EPPC, Notification, AppleEvents, AERegistry, Script, Packages, Dialogs, CTBUtilities, Connections, Menus, TextEdit, Traps, Balloons, wBMGlobals, wBMMiscSubs, OffScreenSubs, wBMScrollSubs, wBarMenuProc, wBMBalloons, wBMWindSubs, myAppleEvents;
  26.  
  27.  
  28.  
  29.  
  30. { ----------------------- }
  31. { Guess what this does ?? }
  32. { ----------------------- }
  33.  
  34.     PROCEDURE HandleCursor;
  35.  
  36.         VAR
  37.             PlusCurs, TECurs: CursHandle;
  38.             mouse: Point;
  39.             rightSB, bottomSB: Rect;
  40.  
  41.  
  42.     BEGIN
  43.  
  44.         IF currDA | NOT myAppl THEN
  45.             EXIT(HandleCursor);                      { DAs & other applications roll their own }
  46.  
  47.         WITH FW^ DO
  48.         BEGIN
  49.  
  50.             GetMouse(mouse);
  51.             ;
  52.             IF applWind THEN
  53.             BEGIN
  54.                 InWindow := PtInRect(mouse, portRect);
  55.                 GetWBMrects(FW, WBMrect, leftMSArect, rightMSArect);
  56.                 IF NOT EmptyRect(WBMrect) THEN
  57.                     InWBMenu := PtInRect(mouse, WBMrect)
  58.                 ELSE
  59.                     InWBMenu := FALSE;                   { NO Window Bar Menu. }
  60.             END
  61.             ELSE   { Zip windows or a DA is up }
  62.                 InWindow := FALSE;                     { By definition, InWBMenu := FALSE. }
  63.  
  64.             IF NOT InWindow THEN
  65.                 InitCursor
  66.  
  67.             ELSE
  68.             BEGIN
  69.  
  70.                 IF InWBMenu THEN
  71.                     InitCursor                           { Cursor in Window Bar Menu. }
  72.  
  73.                 ELSE IF (windType = rDocProc) THEN   { My startup "rDocProc" window. }
  74.                 BEGIN
  75.                     PlusCurs := GetCursor(plusCursor);
  76.                     SetCursor(PlusCurs^^);
  77.                 END
  78.  
  79.                 ELSE                                  { In Scroll Bars or not ??? }
  80.  
  81.                 BEGIN
  82.                     rightSB := portRect;
  83.                     bottomSB := portRect;
  84.                     IF hasGrowIcon THEN
  85.                     BEGIN
  86.                         WITH rightSB DO
  87.                             left := right - (scrollWidth - frame);
  88.                         WITH bottomSB DO
  89.                             top := bottom - (scrollHeight - frame);
  90.                     END;
  91.  
  92.                     IF PtInRect(mouse, rightSB) | PtInRect(mouse, bottomSB) THEN
  93.                         InitCursor
  94.                     ELSE
  95.                     BEGIN
  96.                         TECurs := GetCursor(iBeamCursor);
  97.                         SetCursor(TECurs^^);
  98.                     END;
  99.                 END;   { InWindow, NOT InWBMenu, zoomDocProc window }
  100.  
  101.             END;   { IF InWindow }
  102.  
  103.         END;   { WITH }
  104.  
  105.     END;   { HandleCursor }
  106.  
  107.  
  108.  
  109. { ----------------------------------------------------------------- }
  110. { PeriodicMenus is called before action is taken on menu commands   }
  111. { to correctly enable or disable the "Edit" Menu in case a Desk     }
  112. { Accessory owns the front window or no window is up, respectively. }
  113. { The latter also affects individual items in the other Menu(s).    }
  114. { ----------------------------------------------------------------- }
  115.  
  116.     PROCEDURE PeriodicMenus;
  117.  
  118.         CONST
  119.             wholeMenu = 0;
  120.  
  121.         VAR
  122.             daWind: BOOLEAN;
  123.             redraw: BOOLEAN;             { Used to avoid a flickering MenuBar. }
  124.  
  125.  
  126.         PROCEDURE SetEnable (menu: MenuHandle; item: INTEGER; tobeEnabled: BOOLEAN);
  127.   { --------------------- }
  128.   { To be or not to be !! }
  129.   { --------------------- }
  130.  
  131.         BEGIN
  132.             IF tobeEnabled THEN
  133.                 EnableItem(menu, item)
  134.             ELSE
  135.                 DisableItem(menu, item);
  136.         END;   { SetEnable }
  137.  
  138.  
  139.         FUNCTION daMenu: BOOLEAN;
  140.   { I know ... NEVER assume knowledge of Menu Record structures ... BUT ... }
  141.  
  142.             CONST
  143.                 MenuListLoc = $A1C;
  144.  
  145.             TYPE
  146.                 rMenuRec = RECORD
  147.                         menuOH: MenuHandle;
  148.                         menuLeft: INTEGER;                 { Left edge of Menu. }
  149.                     END;   { rMenuRec }
  150.  
  151.                 hMenuRec = RECORD
  152.                         menuHOH: MenuHandle;
  153.                         reserved: INTEGER;
  154.                     END;   { hMenuRec }
  155.  
  156.                 MenuList = RECORD
  157.                         lastMenu: INTEGER;                 { Offset to last regular MenuHandle. }
  158.                         lastRight: INTEGER;                { Right edge of last Menu's title. }
  159.                         mbResID: INTEGER;
  160.                         rMenu: ARRAY[0..0] OF rMenuRec;
  161.           { The following fields are also present:                                 }
  162.           {                                                                        }
  163.           { lastHMenu: INTEGER;  --  Offset from here to last hierarchical Menu.   }
  164.           { menuTitleSave: PixMapHandle;                                           }
  165.           { hMenu: ARRAY[0..0] OF hMenuRec;  --  When my daMenu routine is called, }
  166.           {                                      there are NO hierarchical Menus.  }
  167.                     END;   { MenuList }
  168.  
  169.                 MenuListPtr = ^MenuList;
  170.                 MenuListHdl = ^MenuListPtr;
  171.  
  172.             VAR
  173.                 MLHdl: MenuListHdl;
  174.                 nbrMenusX6, menuCounter, theMenuID: INTEGER;
  175.  
  176.  
  177.         BEGIN
  178.  
  179.             MLHdl := MenuListHdl(longPtr(MenuListLoc)^);
  180.             nbrMenusX6 := ORD(MLHdl^^.lastMenu);
  181.             menuCounter := (nbrMenusX6 DIV 6) - 1;
  182.  
  183.             WHILE menuCounter >= 0 DO
  184.             BEGIN
  185.                 theMenuID := MLHdl^^.rMenu[menuCounter].menuOH^^.menuID;
  186.       { Watch out !!! with System 7 ... }
  187.       { ... the Help Menu (kHMHelpMenuID = -16490) & }
  188.       { ... the Application Menu (ID = ???)          }
  189.                 IF (theMenuID < 0) & (theMenuID >= -16384) THEN
  190.                     Leave;
  191.                 menuCounter := menuCounter - 1;
  192.             END;   { scanning the MenuBar }
  193.  
  194.     { I could have used:                                               }
  195.     {           daMenu := theMenuID < 0;                               }
  196.     { because I KNOW my app has menus.  However, to make this routine  }
  197.     { applicable to ANY app, what if ANY app had zip menus and there   }
  198.     { were no DA menus, then I would have to initialize with:          }
  199.     {           theMenuID := 0;                                        }
  200.     { putting an extra statement in a time-critical "doPeriodic" loop. }
  201.             daMenu := menuCounter >= 0;
  202.  
  203.         END;   { daMenu }
  204.  
  205.  
  206.     BEGIN   { PeriodicMenus }
  207.  
  208.         redraw := FALSE;
  209.         FW := FrontWindow;                         { Used by HandleCursor ... }
  210.         daWind := (FW <> NIL) & (WindowPeek(FW)^.windowKind < 0);
  211.         currDA := daWind | daMenu;                 { = FALSE if another application }
  212.                                                {   under MultiFinder.           }
  213.         applWind := (FW <> NIL) & NOT currDA;     { = TRUE if ...                  }
  214.  
  215.         SetEnable(FileMenu, NewWindowItem, NOT currDA & moreNew);
  216.         SetEnable(FileMenu, CloseWindowItem, myAppl & applWind);
  217.   { Item = "Next window":}
  218.         SetEnable(WindowMenu, firstWindowItem - 2, windowCount > 1);
  219.  
  220.         IF (currDA <> prevDA) | (applWind <> prevWind) THEN
  221.         BEGIN
  222.             SetEnable(EditMenu, wholeMenu, daWind | applWind);
  223.             SetEnable(WindowMenu, wholeMenu, applWind);
  224.             redraw := TRUE;
  225.         END;
  226.  
  227.         prevDA := currDA;
  228.         prevWind := applWind;
  229.  
  230.         IF redraw THEN
  231.             DrawMenuBar;
  232.  
  233.     END;   { PeriodicMenus }
  234.  
  235.  
  236.  
  237. { ----------- }
  238. { Bye-Bye !!  }
  239. { ----------- }
  240.  
  241.     PROCEDURE DoQuit;
  242.  
  243.     BEGIN
  244.  
  245.         DoCloseAll;
  246.         DisposHandle(Handle(mBarList));
  247.         HUnlock(Handle(windowStorage));
  248.         DisposHandle(Handle(windowStorage));
  249.         ;
  250.         Done := TRUE;
  251.  
  252.     END;   { DoQuit }
  253.  
  254.  
  255.  
  256.     PROCEDURE DrawContents (window: WindowPtr);
  257.  
  258.         VAR
  259.             savedTEH: TEHandle;
  260.  
  261.  
  262.     BEGIN
  263.  
  264.         EraseRect(window^.portRect);
  265.         savedTEH := textH;
  266.         textH := TEHandle(GetWRefCon(window));
  267.         IF textH <> NIL THEN
  268.             TEUpdate(window^.portRect, textH);
  269.         textH := savedTEH;
  270.         mBar := wGetMenuBar(window);
  271.         IF mBar <> NIL THEN
  272.         BEGIN
  273.             wDrawMSA(mBar);                    { Calls GetWBMrects. }
  274.             wDrawMenuBar(mBar);
  275.         END;   { window has a WBM }
  276.         DrawControls(window);
  277.         IF hasGrowIcon THEN
  278.             DrawGrowIcon(window);
  279.  
  280.     END;   { DrawContents }
  281.  
  282.  
  283.  
  284. { ==================================================== }
  285. { HandleUpdate re-draws any controls, text, or PICTs   }
  286. { as well as the Grow Icon and Window Menu Bar if any. }
  287. { ==================================================== }
  288.  
  289.     PROCEDURE HandleUpdate;
  290.  
  291.         VAR
  292.             savedPort: GrafPtr;                { Must be local parms because windows }
  293.             savedWindType: INTEGER;            { are updated in front-to-back order: }
  294.             savedHasGrowIcon: BOOLEAN;
  295.             savedMBar: wMenuBarHandle;
  296.             savedWBMrect, savedLeftMSArect, savedRightMSArect: Rect;
  297.             window: WindowPtr;
  298.  
  299.  
  300.     BEGIN
  301.  
  302.         GetPort(savedPort);                  { Save stuff ... }
  303.         savedWindType := windType;
  304.         savedHasGrowIcon := hasGrowIcon;
  305.         savedMBar := mBar;
  306.         savedWBMrect := WBMrect;
  307.         savedLeftMSArect := leftMSArect;
  308.         savedRightMSArect := rightMSArect;
  309.  
  310.         window := WindowPtr(Event.message);
  311.         SetPort(window);
  312.         windType := GetWindowType(window);   { Quantifies "hasGrowIcon". }
  313.  
  314.         BeginUpDate(window);
  315.         ;
  316.         DrawContents(window);
  317.         ;
  318.         EndUpdate(window);
  319.  
  320.         SetPort(savedPort);                  { Reset stuff ... }
  321.         windType := savedWindType;
  322.         hasGrowIcon := savedHasGrowIcon;
  323.         mBar := savedMBar;
  324.         WBMrect := savedWBMrect;
  325.         leftMSArect := savedLeftMSArect;
  326.         rightMSArect := savedRightMSArect;
  327.  
  328.         IF NOT EventAvail(updateMask, Event) THEN
  329.             brandNew := FALSE;                 { Everything's updated, already !! }
  330.  
  331.     END;   { HandleUpdate }
  332.  
  333.  
  334.  
  335. { ----------------------------------------------- }
  336. { Need to separate them because we're trying to   }
  337. { make this blasted thing MultiFinder-compatible: }
  338. { ----------------------------------------------- }
  339.  
  340.     PROCEDURE DoDeactivate (window: WindowPtr);
  341.  
  342.     BEGIN
  343.  
  344.   { Remember, deActivate & Activate Events generally come in pairs,  }
  345.   { with deActivate first in line.  SO ... we hide the silly things  }
  346.   { and re-show them after the Resume partner has finished.          }
  347.         IF NOT InForeGround THEN       { A suspend Event. }
  348.         BEGIN
  349.             saveBalloons := balloonsUp;    { Where we're at !!! }
  350.             ResetBalloons(startBalloons);  { On Day Numero Uno !!! }
  351.         END;
  352.  
  353.         IF window = NIL THEN   { Window or not, we still do the Balloon-thing !! }
  354.             EXIT(DoDeactivate);
  355.  
  356.         GetWBMrects(window, WBMrect, leftMSArect, rightMSArect);
  357.         IF NOT EmptyRect(WBMrect) THEN
  358.         BEGIN
  359.  
  360.             gWBMrect := WBMrect;
  361.             LocalGlobal(gWBMrect);
  362.             IF SectRect(gWBMrect, gScreen, visRect) THEN
  363.             BEGIN
  364.                 GlobalLocal(visRect);
  365.                 onScreenRgn := NewRgn;
  366.                 RectRgn(onScreenRgn, visRect);
  367.                 SectRgn(onScreenRgn, window^.visRgn, onScreenRgn);
  368.                 DimRgn(onScreenRgn);
  369.                 DisposeRgn(onScreenRgn);
  370.             END;   { IF part of WBMrect is visible }
  371.  
  372.         END;   { IF window has a Menu Bar }
  373.  
  374.         IF textH <> NIL THEN
  375.             TEDeActivate(textH);
  376.         ourControl := ScrollHoriz(window);
  377.         IF ourControl <> NIL THEN
  378.             HiliteControl(ourControl, 255);
  379.         ;
  380.         ourControl := ScrollVert(window);
  381.         IF ourControl <> NIL THEN
  382.             HiliteControl(ourControl, 255);
  383.         ;
  384.         IF hasGrowIcon THEN
  385.             DrawGrowIcon(window);
  386.  
  387.         myAppl := FALSE;
  388.  
  389.     END;   { DoDeactivate }
  390.  
  391.  
  392.  
  393.     PROCEDURE DoActivate (window: WindowPtr);
  394.  
  395.     BEGIN
  396.  
  397.         IF NOT InForeGround THEN             { Previously suspended. }
  398.         BEGIN
  399.             ResetBalloons(saveBalloons);
  400.             balloonsUp := saveBalloons;
  401.         END;
  402.  
  403.         IF window = NIL THEN                 { ????? }
  404.             EXIT(DoActivate);
  405.  
  406.         mBar := wGetMenuBar(window);
  407.         IF (mBar <> NIL) & NOT brandNew THEN
  408.         BEGIN
  409.             wDrawMSA(mBar);
  410.             wDrawMenuBar(mBar);
  411.         END;   { window has a WBM }
  412.  
  413.         textH := TEHandle(GetWRefCon(window));
  414.         IF textH <> NIL THEN
  415.             TEActivate(textH);
  416.  
  417.         IF NOT brandNew THEN                 { Let update Event handle it. }
  418.         BEGIN
  419.             ourControl := ScrollHoriz(window);
  420.             IF ourControl <> NIL THEN
  421.                 HiliteControl(ourControl, 0);
  422.             ;
  423.             ourControl := ScrollVert(window);
  424.             IF ourControl <> NIL THEN
  425.                 HiliteControl(ourControl, 0);
  426.             ;
  427.             IF hasGrowIcon THEN
  428.                 DrawGrowIcon(window);
  429.         END;   { NOT brandNew }
  430.  
  431.         myAppl := TRUE;
  432.  
  433.     END;   { DoActivate }
  434.  
  435.  
  436.  
  437.     PROCEDURE HandleActivate;
  438.  
  439.         VAR
  440.             window: WindowPtr;
  441.  
  442.  
  443.     BEGIN
  444.  
  445.         window := WindowPtr(Event.message);
  446.         SetPort(window);
  447.         windType := GetWindowType(window);
  448.  
  449.         IF ODD(Event.modifiers) THEN
  450.             DoActivate(window)
  451.         ELSE
  452.             DoDeactivate(window);
  453.  
  454.         PeriodicMenus;                             { Crisper appearance if here also. }
  455.  
  456.     END;   { HandleActivate }
  457.  
  458.  
  459.  
  460.     PROCEDURE System7Braggart;
  461.  
  462.         CONST
  463.             kSystem7 = 132;
  464.  
  465.         VAR
  466.             theWorld: SysEnvRec;
  467.             itDoesMatter: OSErr;
  468.             oldPort: GrafPtr;
  469.             window: WindowPtr;
  470.             myPic: PicHandle;
  471.             wpRect, picRect: Rect;
  472.  
  473.  
  474.     BEGIN
  475.  
  476.         itDoesMatter := SysEnvirons(SysEnvironsVersion, theWorld);
  477.         IF (itDoesMatter = noErr) & (theWorld.systemVersion >= $0700) THEN
  478.         BEGIN
  479.  
  480.             GetPort(oldPort);
  481.  
  482.             window := GetNewWindow(kSystem7, NIL, WindowPtr(-1));
  483.             IF window <> NIL THEN
  484.             BEGIN
  485.                 SetPort(window);
  486.                 wpRect := window^.portRect;
  487.                 ClipRect(wpRect);
  488.                 myPic := GetPicture(kSystem7);
  489.                 ;
  490.                 IF myPic <> NIL THEN
  491.                 BEGIN
  492.                     picRect := wpRect;
  493.                     InsetRect(picRect, 1, 1);
  494.                     DrawPicture(myPic, picRect);     { ... so it's centered. }
  495.                     Delay(60, finalTicks);
  496.                     InvertRect(wpRect);
  497.                     Delay(120, finalTicks);
  498.                     KillPicture(myPic);
  499.                 END;   { Got a picture }
  500.                 ;
  501.                 DisposeWindow(window);
  502.             END;   { Got a window }
  503.  
  504.             SetPort(oldPort);
  505.  
  506.         END;   { Got System 7 }
  507.  
  508.     END;   { System7Braggart }
  509.  
  510.  
  511.  
  512.     PROCEDURE DoSpiffyIris;
  513.  
  514.         LABEL
  515.             100, 200, 300;
  516.  
  517.         CONST
  518.             bragWindowID = 999;
  519.             logoPicID = 131;                           { picFrame :=  54,126,251,540 }
  520.  
  521.         VAR
  522.             bragging: WindowPtr;
  523.             logoPicHdl: PicHandle;
  524.             tempX, tempY: INTEGER;
  525.             windRect, pictRect, bragRect, irisRect: Rect;
  526.             irisRgn: RgnHandle;
  527.             maskPercent: INTEGER;
  528.             bragOSHdl: OffScreenRecHdl;
  529.  
  530.  
  531.     BEGIN
  532.  
  533.         SetCursor(GetCursor(watchCursor)^^);
  534.         GetPort(oldPort);
  535.  
  536.   { Calling GetNewCWindow if "aMac2" spoils the automatic centering }
  537.   { provided by the added "centerMainScreen" field in the rez file. }
  538.         bragging := GetNewWindow(bragWindowID, NIL, WindowPtr(-1));
  539.         IF bragging = NIL THEN
  540.             GOTO 300;
  541.         SetPort(bragging);
  542.         CalcVis(WindowPeek(bragging));           { TOM INIT. }
  543.         ;
  544.         logoPicHdl := GetPicture(logoPicID);
  545.         IF logoPicHdl = NIL THEN
  546.             GOTO 200;
  547.         HLock(Handle(logoPicHdl));
  548.  
  549.   { Need an instantaneous deActivate Event }
  550.   { for any window formerly in front.      }
  551.         IF WNE THEN
  552.             WHILE WaitNextEvent(activMask, Event, Sleep, NIL) DO
  553.                 HandleActivate
  554.         ELSE
  555.             WHILE GetNextEvent(activMask, Event) DO
  556.                 HandleActivate;
  557.  
  558.         bragRect := bragging^.portRect;
  559.  
  560.         WITH bragRect DO
  561.         BEGIN
  562.     { IF ScrollVert(bragging) <> NIL THEN          }
  563.     {   right := (right + frame) - scrollWidth;    }
  564.     { IF ScrollHoriz(bragging) <> NIL THEN         }
  565.     {   bottom := (bottom + frame) - scrollHeight; }
  566.             tempX := right - left;
  567.             tempY := bottom - top;
  568.         END;   { WITH bragRect }
  569.  
  570.   { Because I know my WINDow & PICT sizes, tempX & tempY are always > 0: }
  571.         WITH logoPicHdl^^.picFrame DO
  572.         BEGIN
  573.             tempX := tempX - (right - left);
  574.             tempY := tempY - (bottom - top);
  575.         END;   { WITH logoPicHdl^^.picFrame }
  576.  
  577.         WITH bragRect DO
  578.         BEGIN
  579.             tempX := left + tempX DIV 2;
  580.             tempY := top + tempY DIV 2;
  581.         END;   { WITH bragRect }
  582.  
  583.   { ------------------------------------------- }
  584.   { Place my PICTure into an off screen BitMap. }
  585.   { ------------------------------------------- }
  586.  
  587.         bragOSHdl := CreateOffScreen(bragRect);  { Local window in, local screen back. }
  588.         IF bragOSHdl^^.CreateOffScreenError <> noErr THEN
  589.             GOTO 100;
  590.  
  591.         ClipRect(bragRect);                      { Draw off-screen ... }
  592.         EraseRect(bragRect);                     { Eliminate all stray matter. }
  593.         pictRect := bragRect;                    { Center the PICT ... }
  594.         InsetRect(pictRect, tempX, tempY);
  595.         DrawPicture(logoPicHdl, pictRect);
  596.  
  597.         ToOnScreen(bragOSHdl);                   { Back to "Square 1". }
  598.         windRect := bragOSHdl^^.drawingRect;
  599.         ClipRect(windRect);
  600.         InvertRect(windRect);
  601.  
  602.         BackColor(whiteColor);
  603.         ForeColor(blackColor);
  604.   { ---------- }
  605.         maskPercent := 99;                       { Initialize some stuff ... }
  606.         WITH windRect DO
  607.         BEGIN
  608.             tempX := (right - left) DIV 2;
  609.             tempY := (bottom - top) DIV 2;
  610.         END;   { WITH drawingRect }
  611.         ;
  612.         WHILE maskPercent >= 0 DO
  613.         BEGIN
  614.             irisRect := windRect;
  615.             InsetRect(irisRect, (tempX * maskPercent) DIV 100, (tempY * maskPercent) DIV 100);
  616.             irisRgn := NewRgn;
  617.             OpenRgn;
  618.             WITH irisRect DO
  619.                 FrameRoundRect(irisRect, ((right - left) * maskPercent) DIV 100, ((bottom - top) * maskPercent) DIV 100);
  620.             CloseRgn(irisRgn);
  621.             WITH bragOSHdl^^ DO
  622.             BEGIN
  623.                 SectRgn(irisRgn, origPort^.visRgn, irisRgn);
  624.                 CopyBits(offBitMapPtr^, origPort^.portBits, bragRect, drawingRect, srcCopy, irisRgn);
  625.             END;
  626.             DisposeRgn(irisRgn);
  627.             ;
  628.             IF aMac2 THEN
  629.                 IF colorDepth = 1 THEN
  630.                     Delay(4, finalTicks)               { Black-and-white too doggone fast !! }
  631.                 ELSE
  632.                     Delay(2, finalTicks)               { Color a tad better. }
  633.             ELSE
  634.                 Delay(1, finalTicks);
  635.             ;
  636.             maskPercent := maskPercent - 1;
  637.         END;   { WHILE maskPercent >= 0 }
  638.   { ---------- }
  639.         Delay(120, finalTicks);                  { Take a gander at its beauty !! }
  640.  
  641. 100:
  642.         DisposOffScreen(bragOSHdl);
  643.  
  644.         HUnlock(Handle(logoPicHdl));
  645.         ReleaseResource(Handle(logoPicHdl));
  646. 200:
  647.         DisposeWindow(bragging);                 { Activates the window behind it. }
  648. 300:
  649.         SysBeep(10);                             { Wake Up Call !! }
  650.  
  651.         SetPort(oldPort);
  652.         InitCursor;                              { Just in case a DA doesn't ...  }
  653.         HandleCursor;                            { So CURSor changes immediately. }
  654.  
  655.     END;   { DoSpiffyIris }
  656.  
  657.  
  658.  
  659. { ---------------------------------------------- }
  660. { DoApple is the code for the main "Apple" Menu. }
  661. { The other two main Menus follow.               }
  662. { ---------------------------------------------- }
  663.  
  664.     PROCEDURE DoApple (item: INTEGER);
  665.  
  666.         VAR
  667.             accName: Str255;
  668.             accNumber: INTEGER;
  669.  
  670.  
  671.     BEGIN
  672.  
  673.         CASE item OF
  674.  
  675.             AboutItem: 
  676.                 DoSpiffyIris;
  677.  
  678.             AdisabledItem:                { NEVER seen -- shown for completeness, only. }
  679.             BEGIN
  680.             END;   { AdisabledItem }
  681.  
  682.             OTHERWISE
  683.             BEGIN
  684.                 GetPort(oldPort);
  685.                 ;
  686.                 GetItem(AppleMenu, item, accName);
  687.                 accNumber := OpenDeskAcc(accName);
  688.                 ;
  689.                 SetPort(oldPort);
  690.             END;   { OTHERWISE }
  691.  
  692.         END;   { CASE...OF }
  693.  
  694.     END;   { DoApple }
  695.  
  696.  
  697.  
  698.     PROCEDURE DoFile (item: INTEGER);
  699.  
  700.  
  701.     BEGIN
  702.  
  703.         CASE item OF
  704.  
  705.             NewWindowItem: 
  706.                 ignore := DoNewWindow(newWindowID, wMBARID, offset);
  707.  
  708.             CloseWindowItem: 
  709.                 CloseOurWindow(FrontWindow);
  710.  
  711.             FdisabledItem: 
  712.             BEGIN
  713.             END;
  714.  
  715.             QuitItem: 
  716.             BEGIN
  717.                 Delay(flashDelay, finalTicks);            { Don't ask ????? }
  718.                 DoQuit;
  719.             END;
  720.  
  721.             OTHERWISE
  722.             BEGIN
  723.             END;   { OTHERWISE }
  724.  
  725.         END;   { CASE...OF }
  726.  
  727.     END;   { DoFile }
  728.  
  729.  
  730.  
  731.     PROCEDURE DoEdit (item: INTEGER);
  732.  
  733.     BEGIN
  734.  
  735.         IF SystemEdit(item - 1) THEN
  736.             EXIT(DoEdit);                              { DAs do their own thing !! }
  737.  
  738.         CASE item OF
  739.  
  740.             UndoItem, EdisabledItem, CutItem, CopyItem, PasteItem, ClearItem: 
  741.             BEGIN
  742.             END;
  743.  
  744.         END;   { CASE...OF }
  745.  
  746.     END;   { DoEdit }
  747.  
  748.  
  749.  
  750.     PROCEDURE DoWindow (item: INTEGER);
  751.  
  752.         VAR
  753.             wPeek: WindowPeek;
  754.             itemString, wpTitle: Str255;
  755.  
  756.  
  757.     BEGIN
  758.  
  759.         IF (gInitAppleEvents = noErr) & (item = AEWindItem) THEN
  760.             CreateAndSendAE(kMoveWindClass, kMoveWindID)
  761.         ELSE IF item = firstWindowItem - 2 THEN
  762.         BEGIN
  763.  
  764.             wPeek := WindowPeek(FrontWindow)^.nextWindow;
  765.     { System 6.xx w/DA in application heap: }
  766.             WHILE (wPeek <> NIL) & (wPeek^.windowKind <> userKind) DO
  767.                 wPeek := wPeek^.nextWindow;
  768.             ;
  769.             IF wPeek <> NIL THEN
  770.             BEGIN
  771.                 SelectWindow(WindowPtr(wPeek));
  772.                 UncheckOldItem(WindowMenu);             { Un-check old item ... }
  773.                 item := ItemFromName(wPeek^.titleHandle^^);
  774.                 CheckItem(WindowMenu, item, true);      { & check the new one.  }
  775.             END;   { wPeek <> NIL }
  776.  
  777.         END   { ELSE IF "Next window" }
  778.         ELSE
  779.         BEGIN
  780.  
  781.             GetItem(WindowMenu, item, itemString);
  782.             wPeek := WindowPeek(FrontWindow);
  783.             ;
  784.             WHILE wPeek <> NIL DO
  785.             BEGIN
  786.                 IF wPeek^.windowKind = userKind THEN
  787.                 BEGIN
  788.                     wpTitle := wPeek^.titleHandle^^;
  789.                     IF itemString = wpTitle THEN
  790.                         Leave;   { WHILE loop }
  791.                 END;
  792.                 wPeek := wPeek^.nextWindow;
  793.             END;   { WHILE }
  794.  
  795.             IF wPeek <> NIL THEN
  796.             BEGIN
  797.                 SelectWindow(WindowPtr(wPeek));
  798.                 UncheckOldItem(WindowMenu);
  799.                 CheckItem(WindowMenu, item, true);
  800.             END;
  801.  
  802.         END;   { ELSE }
  803.  
  804.     END;   { DoWindow }
  805.  
  806.  
  807.  
  808. { ----------------------------------------------------- }
  809. { DoWBMApple is the code for the window's "Apple" Menu. }
  810. { The other two window Menus follow.                    }
  811. { ----------------------------------------------------- }
  812.  
  813.     PROCEDURE DoWBMApple (item: INTEGER);
  814.  
  815.         VAR
  816.             accName: Str255;
  817.             accNumber: INTEGER;
  818.  
  819.  
  820.     BEGIN
  821.  
  822.         CASE item OF
  823.  
  824.             wAboutItem: 
  825.                 DoSpiffyIris;
  826.  
  827.             wAdisabledItem:            { NEVER seen -- shown for completeness, only. }
  828.             BEGIN
  829.             END;   { wAdisabledItem }
  830.  
  831.             OTHERWISE
  832.             BEGIN
  833.                 GetPort(oldPort);
  834.                 ;
  835.                 GetItem(AppleMenu, item, accName);
  836.                 accNumber := OpenDeskAcc(accName);
  837.                 ;
  838.                 SetPort(oldPort);
  839.             END;   { OTHERWISE }
  840.  
  841.         END;   { CASE...OF }
  842.  
  843.     END;   { DoWBMApple }
  844.  
  845.  
  846.  
  847.     PROCEDURE DoWBMFile (item: INTEGER);
  848.  
  849.  
  850.     BEGIN
  851.  
  852.         CASE item OF
  853.  
  854.             wNewWindowItem: 
  855.                 ;
  856.  
  857.             wCloseWindowItem: 
  858.                 ;
  859.  
  860.             wFdisabledItem: 
  861.             BEGIN
  862.             END;
  863.  
  864.             wQuitItem: 
  865.                 DoQuit;
  866.  
  867.             OTHERWISE
  868.             BEGIN
  869.             END;   { OTHERWISE }
  870.  
  871.         END;   { CASE...OF }
  872.  
  873.     END;   { DoWBMFile }
  874.  
  875.  
  876.  
  877.     PROCEDURE DoWBMNewHier (item: INTEGER);
  878.  
  879.  
  880.     BEGIN
  881.  
  882.         CASE item OF
  883.  
  884.             wNewHierItem: 
  885.                 ;
  886.  
  887.             OTHERWISE
  888.                 ;
  889.  
  890.         END;   { CASE }
  891.  
  892.     END;   { DoWBMNewHier }
  893.  
  894.  
  895.  
  896.     PROCEDURE DoWBMCloseHier (item: INTEGER);
  897.  
  898.  
  899.     BEGIN
  900.  
  901.         CASE item OF
  902.  
  903.             wCloseHierItem: 
  904.                 ;
  905.  
  906.             OTHERWISE
  907.                 ;
  908.  
  909.         END;   { CASE }
  910.  
  911.     END;   { DoWBMCloseHier }
  912.  
  913.  
  914.  
  915.     PROCEDURE DoWBMHierHier (item: INTEGER);
  916.  
  917.  
  918.     BEGIN
  919.  
  920.         CASE item OF
  921.  
  922.             wHierHierItem: 
  923.                 PlaySound('Bush Inauguration Speech');
  924.  
  925.             OTHERWISE
  926.                 ;
  927.  
  928.         END;   { CASE }
  929.  
  930.     END;   { DoWBMHierHier }
  931.  
  932.  
  933.  
  934.     PROCEDURE DoWBMEdit (item: INTEGER);
  935.  
  936.     BEGIN
  937.  
  938.         IF SystemEdit(item - 1) THEN
  939.             EXIT(DoWBMEdit);                    { DAs do their own thing !! }
  940.  
  941.         CASE item OF
  942.  
  943.             wUndoItem, wEdisabledItem, wCutItem, wCopyItem, wPasteItem, wClearItem: 
  944.             BEGIN
  945.             END;
  946.  
  947.         END;   { CASE...OF }
  948.  
  949.     END;   { DoWBMEdit }
  950.  
  951.  
  952.  
  953. { ------------------------------------------------------------ }
  954. { HandleMainMenu is the dispatch routine for the main MenuBar. }
  955. { The item selected is passed to the appropriate menu handler. }
  956. { ------------------------------------------------------------ }
  957.  
  958.     PROCEDURE HandleMainMenu;
  959.  
  960.         VAR
  961.             menuCode: LONGINT;
  962.             charCode: INTEGER;
  963.  
  964.     BEGIN
  965.         IF Event.what = MouseDown THEN
  966.             menuCode := MenuSelect(Event.where)
  967.         ELSE
  968.         BEGIN
  969.             charCode := BitAnd(Event.message, CharCodeMask);
  970.             menuCode := MenuKey(CHR(charCode));
  971.         END;   { ELSE }
  972.  
  973.         CASE HiWord(menuCode) OF
  974.             AppleMenuID: 
  975.                 DoApple(LoWord(menuCode));
  976.  
  977.             FileMenuID: 
  978.                 DoFile(LoWord(menuCode));
  979.  
  980.             EditMenuID: 
  981.                 DoEdit(LoWord(menuCode));
  982.  
  983.             mWindow: 
  984.                 DoWindow(LoWord(menuCode));
  985.  
  986.             kHMHelpMenuID: 
  987.                 IF LoWord(menuCode) = origNumHelpItems + 1 THEN
  988.         { User selected my Item which I appended in "SetupMainMenus" PROC. }
  989.                     DoSpiffyIris;
  990.  
  991.             OTHERWISE
  992.                 IF Event.what = KeyDown THEN
  993.                     SysBeep(10);
  994.         END;   { CASE }
  995.  
  996.         HiliteMenu(0)
  997.     END;   { HandleMainMenu }
  998.  
  999.  
  1000.  
  1001. { ----------------------------------------------------------- }
  1002. { Ditto for the Window Bar Menu, except for a slight twist.   }
  1003. { The change from a PROCEDURE to a FUNCTION is required when  }
  1004. { a CMD-key is pressed.  The Window Menus take precedence and }
  1005. { if the CMD-key is not found in the window's Menu List, then }
  1006. { we go to "HandleMainMenu".                                  }
  1007. { ----------------------------------------------------------- }
  1008.  
  1009.     FUNCTION HandleWBMenu (theMenuBar: wMenuBarHandle): BOOLEAN;
  1010.  
  1011.         VAR
  1012.             WBMenuCode: LONGINT;
  1013.             WBMCharCode: INTEGER;
  1014.  
  1015.     BEGIN
  1016.  
  1017.         HandleWBMenu := TRUE;                   { Be optimistic !! }
  1018.  
  1019.         IF Event.what = MouseDown THEN
  1020.             WBMenuCode := wMenuSelect(theMenuBar, Event.where)
  1021.         ELSE
  1022.         BEGIN
  1023.             WBMCharCode := BitAnd(Event.message, CharCodeMask);
  1024.             WBMenuCode := wMenuKey(theMenuBar, CHR(WBMCharCode));
  1025.         END;   { ELSE }
  1026.  
  1027.         CASE HiWord(WBMenuCode) OF
  1028.             wAppleMenuID: 
  1029.                 DoWBMApple(LoWord(WBMenuCode));
  1030.             wFileMenuID: 
  1031.                 DoWBMFile(LoWord(WBMenuCode));
  1032.             wEditMenuID: 
  1033.                 DoWBMEdit(LoWord(WBMenuCode));
  1034.             wNewHierMenuID:                      { Sub-menus under "File" ... }
  1035.                 DoWBMNewHier(LoWord(WBMenuCode));
  1036.             wCloseHierMenuID: 
  1037.                 DoWBMCloseHier(LoWord(WBMenuCode));
  1038.             wHierHierMenuID: 
  1039.                 DoWBMHierHier(LoWord(WBMenuCode));
  1040.             OTHERWISE
  1041.                 IF Event.what = KeyDown THEN
  1042.                     HandleWBMenu := FALSE;
  1043.         END;   { CASE }
  1044.  
  1045.         wHiliteMenu(theMenuBar, 0)
  1046.  
  1047.     END;   { HandleWBMenu }
  1048.  
  1049.  
  1050.  
  1051.     PROCEDURE SetUpMainMenus;
  1052.  
  1053.         CONST
  1054.             none = 0;
  1055.  
  1056.         VAR
  1057.             theWorld: SysEnvRec;
  1058.             takeItOrLeaveIt: OSErr;
  1059.  
  1060.  
  1061.     BEGIN
  1062.  
  1063.         AppleMenu := GetMenu(AppleMenuID);
  1064.         takeItOrLeaveIt := SysEnvirons(1, theWorld);
  1065.         IF theWorld.systemVersion < $0700 THEN
  1066.         BEGIN
  1067.             SetItemIcon(AppleMenu, AboutItem, none);
  1068.             SetItemCmd(AppleMenu, AboutItem, char(none));
  1069.         END;
  1070.         InsertMenu(AppleMenu, 0);
  1071.         AddResMenu(AppleMenu, 'DRVR');              { + DAs }
  1072.         ;
  1073.         FileMenu := GetMenu(FileMenuID);
  1074.         InsertMenu(FileMenu, 0);
  1075.   { myAppl := TRUE;     --     taken care of by 1st Activate Event. }
  1076.         prevWind := TRUE;
  1077.         ;
  1078.         EditMenu := GetMenu(EditMenuID);
  1079.         InsertMenu(EditMenu, 0);
  1080.         prevDA := FALSE;
  1081.         ;
  1082.         AddWindowMenu;
  1083.  
  1084.         HelpMenu := NIL;
  1085.         IF HelpManagerActive THEN
  1086.             IF HMGetHelpMenuHandle(HelpMenu) = noErr THEN
  1087.                 IF HelpMenu <> NIL THEN
  1088.                 BEGIN
  1089.                     origNumHelpItems := CountMItems(HelpMenu);
  1090.                     AppendMenu(HelpMenu, 'About Window Bar Menu Demo ...');
  1091.                 END;
  1092.  
  1093.         DrawMenuBar;
  1094.  
  1095.     END;   { SetUpMainMenus }
  1096.  
  1097.  
  1098.  
  1099. { --------------------------------------------------------------- }
  1100. { Make a separate PROC so we can zoom independently of _TrackBox, }
  1101. { for example, in response to a Menu selection or a keypress:     }
  1102. { --------------------------------------------------------------- }
  1103.  
  1104.     PROCEDURE doZoom (window: WindowPtr; zoomDir: INTEGER);
  1105. { Reference: Tech Note #79 }
  1106.  
  1107.         TYPE
  1108.             WStateDataPtr = ^WStateData;
  1109.             WStateDataHandle = ^WStateDataPtr;
  1110.  
  1111.         VAR
  1112.             windRect, zoomRect: Rect;
  1113.             dominantGDevice: GDHandle;
  1114.             bias: INTEGER;
  1115.  
  1116.  
  1117.     BEGIN
  1118.  
  1119.         IF NOT applWind THEN
  1120.             EXIT(doZoom);
  1121.         ;
  1122.         GetPort(oldPort);
  1123.         SetPort(window);
  1124.  
  1125.   { If there is the possibility of multiple gDevices, then we must check them   }
  1126.   { to make sure we are zooming onto the right display device when zooming out. }
  1127.         IF (zoomDir = inZoomOut) AND aMac2 THEN
  1128.         BEGIN
  1129.  
  1130.     { Window's portRect must be converted to global coordinates: }
  1131.             windRect := window^.portRect;
  1132.             LocalGlobal(windRect);
  1133.  
  1134.     { Must calculate height of window's title bar }
  1135.             bias := windRect.top - 1 - WindowPeek(window)^.strucRgn^^.rgnBBox.top;
  1136.             windRect.top := windRect.top - bias;
  1137.  
  1138.             dominantGDevice := GetMaxAreaDevice(windRect);
  1139.  
  1140.     { We must create a zoom rectangle manually in this case & }
  1141.     { account for menu bar height as well, if on main device. }
  1142.             IF dominantGDevice = GetMainDevice THEN
  1143.                 bias := bias + mBarHt;
  1144.             WITH dominantGDevice^^.gdRect DO
  1145.                 SetRect(zoomRect, left + 3, top + bias + 3, right - 3, bottom - 3);
  1146.  
  1147.     { Set up the WStateData record for this window. }
  1148.             WStateDataHandle(WindowPeek(window)^.dataHandle)^^.stdState := zoomRect;
  1149.  
  1150.         END; { inZoomOut & color Quickdraw }
  1151.  
  1152.         EraseRect(window^.portRect);
  1153.         ShowHide(window, FALSE);
  1154.         ZoomWindow(window, zoomDir, FALSE);      { NO Activate Event !! }
  1155.         InvalRect(window^.portRect);
  1156.         ScrollResize(window);
  1157.         wChangeMenuBarSize(window, zooming);
  1158.         ShowHide(window, TRUE);
  1159.  
  1160.         CASE zoomDir OF
  1161.  
  1162.             inZoomOut: 
  1163.                 PlaySound('ZoomOut');
  1164.  
  1165.             inZoomIn: 
  1166.                 PlaySound('ZoomIn');
  1167.  
  1168.             OTHERWISE                             { Nada !! }
  1169.             BEGIN
  1170.             END;
  1171.  
  1172.         END;   { CASE }
  1173.  
  1174.         SetPort(oldPort);
  1175.  
  1176.     END;   { doZoom }
  1177.  
  1178.  
  1179.  
  1180.     PROCEDURE HandleMouse;
  1181.  
  1182.         CONST
  1183.             growing = NOT zooming;
  1184.  
  1185.         VAR
  1186.             dragRect, windRect, growRect: Rect;
  1187.             newSize: LONGINT;
  1188.             titleBarHeight, windWidth, windHt, tempINT, i: INTEGER;
  1189.             mouseLoc: Point;
  1190.             partControl: INTEGER;
  1191.             dontCareThisTimeAboutTheResult: BOOLEAN;
  1192.  
  1193.  
  1194.     BEGIN
  1195.  
  1196.         CASE windowLoc OF
  1197.  
  1198.             inDesk: 
  1199.             BEGIN
  1200.  
  1201.             END;   { inDesk }
  1202.  
  1203.             inMenuBar: 
  1204.                 HandleMainMenu;
  1205.  
  1206.             inSysWindow: 
  1207.                 SystemClick(Event, TheWindow);          { TheWindow = DA window }
  1208.  
  1209.             inContent: 
  1210.             BEGIN
  1211.  
  1212.                 IF TheWindow <> FrontWindow THEN
  1213.                 BEGIN
  1214.                     SelectWindow(TheWindow);              { Generates an Activate Event. }
  1215.                     IF WindowPeek(TheWindow)^.windowKind = userKind THEN
  1216.                     BEGIN
  1217.                         UncheckOldItem(WindowMenu);
  1218.                         GetWTitle(TheWindow, windowName);
  1219.                         CheckItem(WindowMenu, ItemFromName(windowName), true);
  1220.                     END;   { userKind }
  1221.                     EXIT(HandleMouse);
  1222.                 END;   { IF TheWindow <> FrontWindow }
  1223.  
  1224.                 mouseLoc := Event.where;
  1225.                 GlobalToLocal(mouseLoc);
  1226.                 partControl := FindControl(mouseLoc, TheWindow, ourControl);
  1227.                 IF partControl <> 0 THEN   { Nada !! }
  1228.                 BEGIN
  1229.  
  1230.                 END
  1231.  
  1232.       { mBar & rects gotten from "DoActivate" or "HandleUpdate" }
  1233.                 ELSE IF (mBar <> NIL) & PtInRect(mouseLoc, WBMrect) THEN
  1234.                 BEGIN
  1235.  
  1236.                     HideBalloons(balloonsUp);              { ... IF they're showing to begin with. }
  1237.                     ;
  1238.                     IF PtInRect(mouseLoc, leftMSArect) | PtInRect(mouseLoc, rightMSArect) THEN
  1239.                         wScrollMenuBar(mBar)
  1240.                     ELSE
  1241.                         dontCareThisTimeAboutTheResult := HandleWBMenu(mBar);
  1242.                     ;
  1243.                     ShowBalloons(balloonsUp);              { ... that is if they were up initially. }
  1244.  
  1245.                 END   { somewhere in the WBM }
  1246.  
  1247.                 ELSE IF DoubleClick THEN               { NO mBar or NOT in WBMrect }
  1248.                     DoFile(QuitItem);
  1249.  
  1250.             END;   { inContent }
  1251.  
  1252.             inDrag: 
  1253.             BEGIN
  1254.  
  1255.                 IF balloonsUp THEN
  1256.                 BEGIN
  1257.                     HideBalloons(true);
  1258.                     IF EventAvail(updateMask, Event) THEN
  1259.           { Need an instantaneous update Event because of the Title Bar's balloon: }
  1260.                         IF WNE THEN
  1261.                             WHILE WaitNextEvent(updateMask, Event, Sleep, NIL) DO
  1262.                                 HandleUpdate
  1263.                         ELSE
  1264.                             WHILE GetNextEvent(updateMask, Event) DO
  1265.                                 HandleUpdate;
  1266.                 END;   { IF }
  1267.  
  1268.                 dragRect := gScreen;                  { Includes main MenuBar. }
  1269.                 ;
  1270.                 WITH dragRect DO
  1271.                 BEGIN
  1272.                     top := top + mBarHt;                { Back to exclude. }
  1273.         { Do NOT hide part of wMenuBar when dragging to bottom: }
  1274.                     IF mBar <> NIL THEN
  1275.                         bottom := bottom - mBarHt;
  1276.                     InsetRect(dragRect, 10, 0);         { + horizontal = just a tad. }
  1277.         { Do NOT hide part of window's title bar.                    }
  1278.         { May be CMD-dragging, so we have to save & restore thePort: }
  1279.                     GetPort(oldPort);
  1280.                     SetPort(TheWindow);
  1281.                     windRect := TheWindow^.portRect;
  1282.                     LocalGlobal(windRect);
  1283.                     titleBarHeight := windRect.top - 1 - WindowPeek(TheWindow)^.strucRgn^^.rgnBBox.top;
  1284.                     InsetRect(dragRect, 0, titleBarHeight);
  1285.                     SetPort(oldPort);
  1286.                 END;   { WITH dragRect }
  1287.  
  1288.       { _DragWindow forces the Mouse to stay inside of dragRect. }
  1289.                 DragWindow(TheWindow, Event.where, dragRect);
  1290.  
  1291.                 ShowBalloons(balloonsUp);
  1292.  
  1293.                 IF EventAvail(activMask, Event) THEN
  1294.                     IF WindowPeek(TheWindow)^.windowKind = userKind THEN
  1295.                     BEGIN
  1296.                         UncheckOldItem(WindowMenu);
  1297.                         GetWTitle(TheWindow, windowName);
  1298.                         CheckItem(WindowMenu, ItemFromName(windowName), true);
  1299.                     END;   { pending activate Event + userKind }
  1300.  
  1301.             END;   { inDrag }
  1302.  
  1303.             inGrow: 
  1304.             BEGIN
  1305.  
  1306.                 WITH lScreen DO
  1307.                     SetRect(growRect, 2 * title, 2 * title, right - left, bottom - top);
  1308.  
  1309.                 WITH growRect DO
  1310.                 BEGIN
  1311.                     IF hasGrowIcon THEN
  1312.                     BEGIN
  1313.                         top := top + growBoxSize;
  1314.                         left := left + growBoxSize;
  1315.                     END;
  1316.  
  1317.                     IF ScrollVert(TheWindow) <> NIL THEN
  1318.                     BEGIN
  1319.                         tempINT := (7 * scrollHeight) DIV 2 + growBoxSize;
  1320.                         IF tempINT > top THEN
  1321.                             top := tempINT;
  1322.                     END;
  1323.                     ;
  1324.                     IF ScrollHoriz(TheWindow) <> NIL THEN
  1325.                     BEGIN
  1326.                         tempINT := (7 * scrollWidth) DIV 2 + growBoxSize;
  1327.                         IF tempINT > left THEN
  1328.                             left := tempINT;
  1329.                     END;
  1330.  
  1331.                     IF mBar <> NIL THEN
  1332.                     BEGIN
  1333.                         tempINT := leftMSArect.right - leftMSArect.left + StringWidth('ABCDE') + rightMSArect.right - rightMSArect.left;
  1334.                         IF tempINT > left THEN
  1335.                             left := tempINT;
  1336.                         tempINT := 2 * mBarHt;
  1337.                         IF tempINT > top THEN
  1338.                             top := tempINT;
  1339.                     END;
  1340.                 END;   { WITH growRect }
  1341.  
  1342.                 newSize := GrowWindow(TheWindow, Event.where, growRect);
  1343.                 IF newSize = 0 THEN
  1344.                     EXIT(HandleMouse);                     { NO change. }
  1345.  
  1346.       { ALL of the following just to avoid that pesky (ARRGH !!!)  }
  1347.       { double re-draw of the Scroll Bars.  [See _ValidRect within }
  1348.       { "Inside Macintosh"]  In addition, note that we start out   }
  1349.       { by erasing the grow box because upon enlarging the window, }
  1350.       { the grow icon remains drawn where it used to be just for a }
  1351.       { split second until _BeginUpdate ... _EndUpdate gets around }
  1352.       { to erasing it.                                             }
  1353.  
  1354.                 IF hasGrowIcon THEN
  1355.                     WITH updateRect DO
  1356.                     BEGIN
  1357.                         updateRect := TheWindow^.portRect;
  1358.                         left := right + frame - growBoxSize;
  1359.                         top := bottom + frame - growBoxSize;
  1360.                         EraseRect(updateRect);
  1361.                     END;   { Erasing grow box }
  1362.                 InvalidScroll(TheWindow);
  1363.                 wChangeMenuBarSize(TheWindow, growing);
  1364.                 SizeWindow(TheWindow, LoWord(newSize), HiWord(newSize), TRUE);
  1365.                 wChangeMenuBarSize(TheWindow, growing);
  1366.                 ScrollResize(TheWindow);
  1367.                 ValidScroll(TheWindow);
  1368.                 IF hasGrowIcon THEN
  1369.                     DrawGrowIcon(TheWindow);
  1370.  
  1371.             END;   { inGrow }
  1372.  
  1373.             inGoAway: 
  1374.             BEGIN
  1375.  
  1376.                 IF TrackGoAway(TheWindow, Event.where) THEN
  1377.                     CloseOurWindow(TheWindow);
  1378.  
  1379.             END;   { inGoAway }
  1380.  
  1381.             inZoomOut, inZoomIn: 
  1382.                 IF TrackBox(TheWindow, Event.where, windowLoc) THEN
  1383.                 BEGIN
  1384.                     doZoom(TheWindow, windowLoc);
  1385.                     WITH mBar^^ DO
  1386.                         IF windowLoc = inZoomOut THEN
  1387.                         BEGIN
  1388.  
  1389.             { Scroll right now = back to scratch: }
  1390.                             tempInt := leftMSArect.right + betweenTitles - invertOverlap - wMenus[0].titleRect.left;
  1391.             { Scroll left upon returning = where we are now: }
  1392.                             saveCumScrollMenuX := -tempInt;
  1393.             { Gotta PRE-scroll, otherwise Window Menu Bar is cut off  }
  1394.             { at left since we do NOT keep the off-screen Map around. }
  1395.                             FOR i := 0 TO (numMenus - 1) DO
  1396.                                 OffsetRect(wMenus[i].titleRect, tempInt, 0);
  1397.  
  1398.                         END
  1399.                         ELSE   { zooming back in }
  1400.                             FOR i := 0 TO (numMenus - 1) DO
  1401.                                 OffsetRect(wMenus[i].titleRect, saveCumScrollMenuX, 0);
  1402.                 END;   { zooming }
  1403.  
  1404.         END;   { CASE }
  1405.  
  1406.     END;   { HandleMouse }
  1407.  
  1408.  
  1409.  
  1410.     PROCEDURE HandleKey;
  1411.  
  1412.         VAR
  1413.             keyASCII: INTEGER;
  1414.             yourBalloonIsShowing, handledByWBM: BOOLEAN;
  1415.  
  1416.  
  1417.     BEGIN
  1418.  
  1419.         IF NOT myAppl THEN
  1420.             EXIT(HandleKey);
  1421.  
  1422.         IF BitAnd(Event.modifiers, $0F00) = cmdKey THEN     { ONLY the Command Key }
  1423.             IF applWind THEN
  1424.             BEGIN
  1425.                 mBar := wGetMenuBar(FW);
  1426.                 ;
  1427.                 IF mBar <> NIL THEN
  1428.                 BEGIN
  1429.                     yourBalloonIsShowing := BalloonShowing;
  1430.                     HideBalloons(yourBalloonIsShowing);
  1431.                     handledByWBM := HandleWBMenu(mBar);
  1432.                     ShowBalloons(yourBalloonIsShowing);
  1433.                 END   { a WBMenu }
  1434.                 ELSE
  1435.                     handledByWBM := FALSE;
  1436.                 ;
  1437.                 IF NOT handledByWBM THEN
  1438.                     HandleMainMenu;
  1439.             END
  1440.             ELSE          { NO windows at all !! }
  1441.                 HandleMainMenu
  1442.  
  1443.         ELSE   { no Command Key }
  1444.  
  1445.         BEGIN
  1446.             keyASCII := BitAnd(Event.message, CharCodeMask);
  1447.             IF keyASCII = Enter THEN
  1448.                 DoQuit;
  1449.         END;   { ELSE no Command Key }
  1450.  
  1451.     END;   { HandleKey }
  1452.  
  1453.  
  1454.  
  1455.     PROCEDURE DoPeriodic;
  1456.  
  1457.  
  1458.     BEGIN
  1459.  
  1460.         IF NOT WNE THEN
  1461.             SystemTask;
  1462.  
  1463.         aMac2 := TestForColor(colorDepth);
  1464.         PeriodicMenus;                    { Feeds HandleCursor ... }
  1465.         HandleCursor;
  1466.         IF InForeGround THEN
  1467.         BEGIN
  1468.             IF applWind THEN
  1469.                 IF textH <> NIL THEN
  1470.                     TEIdle(textH);
  1471.             balloonsUp := BalloonsOn;
  1472.             FindAndShowDynamicBalloons(balloonsUp, FW);
  1473.         END
  1474.         ELSE
  1475.             startBalloons := BalloonsOn;
  1476.         ;
  1477.         IF Sleep = 1 THEN
  1478.             Sleep := GetCaretTime;          { Reset after special effects. }
  1479.  
  1480.   { Problems with "Switch-A-Roo" ... }
  1481.   { It eliminates my Help MENU item. }
  1482.         IF myAppl THEN
  1483.     { For some ??? reason the next two IFs are required here }
  1484.     { even though "SetupMainMenus" would not have a non-NIL  }
  1485.     { Help MenuHandle unless they were true.                 }
  1486.             IF HelpManagerActive THEN
  1487.                 IF HMGetHelpMenuHandle(HelpMenu) = noErr THEN
  1488.                     IF HelpMenu <> NIL THEN
  1489.                         IF CountMItems(HelpMenu) = origNumHelpItems THEN
  1490.                             AppendMenu(HelpMenu, 'About Window Bar Menu Demo ...');
  1491.  
  1492.     END;   { DoPeriodic }
  1493.  
  1494.  
  1495.  
  1496.     PROCEDURE MainEventLoop;
  1497.  
  1498.     BEGIN
  1499.  
  1500.         REPEAT
  1501.  
  1502.             IF WNE THEN
  1503.                 ignore := WaitNextEvent(everyEvent, Event, Sleep, NIL)
  1504.             ELSE
  1505.                 ignore := GetNextEvent(everyEvent, Event);
  1506.  
  1507.             CASE Event.what OF
  1508.  
  1509.                 NullEvent: 
  1510.                     DoPeriodic;
  1511.  
  1512.                 MouseDown: 
  1513.                 BEGIN
  1514.                     windowLoc := FindWindow(Event.where, TheWindow);     { Fills in 'TheWindow'. }
  1515.                     HandleMouse;
  1516.                 END;
  1517.  
  1518.                 MouseUp: 
  1519.                 BEGIN
  1520.                 END;
  1521.  
  1522.                 KeyDown, AutoKey: 
  1523.                     HandleKey;
  1524.  
  1525.                 KeyUp: 
  1526.                 BEGIN
  1527.                 END;
  1528.  
  1529.                 UpdateEvt: 
  1530.                     HandleUpdate;
  1531.  
  1532.                 DiskEvt: 
  1533.                 BEGIN
  1534.                 END;
  1535.  
  1536.                 ActivateEvt: 
  1537.                     HandleActivate;
  1538.  
  1539.                 NetworkEvt, DriverEvt: 
  1540.                 BEGIN
  1541.                 END;
  1542.  
  1543.                 App1Evt, App2Evt, App3Evt: 
  1544.                 BEGIN
  1545.                 END;
  1546.  
  1547.                 OSEvt:                                     { MultiFinder Event = app4Evt }
  1548.  
  1549.                 BEGIN
  1550.  
  1551.                     CASE BSR(Event.message, 24) OF          { High byte }
  1552.  
  1553.                         mouseMovedMessage: 
  1554.                             HandleCursor;
  1555.  
  1556.                         suspendResumeMessage: 
  1557.  
  1558.                         BEGIN
  1559.  
  1560.                             IF BAND(Event.message, resumeFlag) <> 0 THEN
  1561.                             BEGIN
  1562.                                 DoActivate(FrontWindow);
  1563.                                 InForeGround := TRUE;
  1564.                             END   { Resume }
  1565.                             ELSE   { Suspend }
  1566.                             BEGIN
  1567.                                 InForeGround := FALSE;
  1568.                                 DoDeactivate(FrontWindow);
  1569.                             END;   { ELSE }
  1570.  
  1571.                         END;   { suspendResumeMessage }
  1572.  
  1573.                         OTHERWISE
  1574.                     END;   { CASE BSR(Event.message, 24) OF }
  1575.  
  1576.                 END;   { MultiFinder Event }
  1577.  
  1578.                 kHighLevelEvent: 
  1579.                 BEGIN
  1580.  
  1581.                     HideBalloons(balloonsUp);                { ... because of my Alert Dialog. }
  1582.                     IF HelpManagerActive THEN
  1583.                         IF HMGetHelpMenuHandle(HelpMenu) = noErr THEN
  1584.                             IF HelpMenu <> NIL THEN
  1585.                             BEGIN
  1586.                                 DisableItem(HelpMenu, kHMShowBalloonsItem);   { Keep them hidden. }
  1587.                                 DrawMenuBar;
  1588.                             END;
  1589.                     ;
  1590.                     DoHighLevelEvent(Event);
  1591.                     ;
  1592.                     ShowBalloons(balloonsUp);
  1593.                     IF HelpManagerActive THEN
  1594.                         IF HMGetHelpMenuHandle(HelpMenu) = noErr THEN
  1595.                             IF HelpMenu <> NIL THEN
  1596.                             BEGIN
  1597.                                 EnableItem(HelpMenu, kHMShowBalloonsItem);     { Reset them. }
  1598.                                 DrawMenuBar;
  1599.                             END;
  1600.  
  1601.                 END;   { HighLevelEvent }
  1602.  
  1603.                 OTHERWISE
  1604.             END;  { CASE Event.what OF }
  1605.  
  1606.         UNTIL Done;
  1607.  
  1608.     END;   { MainEventLoop }
  1609.  
  1610.  
  1611.  
  1612.  
  1613. BEGIN   { Program }
  1614.  
  1615.     InitManagers;                  { The usual stuff ... }
  1616.     ;
  1617.     ROM := wordPtr(ROM85Loc);      { Quantify some globals ... }
  1618.     IF ROM^ > 0 THEN
  1619.         mBarHt := GetMBarHeight
  1620.     ELSE
  1621.         ExitToShell;                 { NO workee !!! }
  1622.     ;
  1623.     gInitAppleEvents := InitAppleEvents;   { errs in "myAppleEvents.p" ... }
  1624.     gInitPPCToolbox := InitPPCToolbox;
  1625.  
  1626.     SetCursor(GetCursor(watchCursor)^^);
  1627.     ;
  1628.     lScreen := screenBits.bounds;
  1629.     gScreen := GetGrayRgn^^.rgnBBox;
  1630.     WITH gScreen DO
  1631.         top := top - mBarHt;         { Include main MenuBar. }
  1632.     WITH lScreen DO
  1633.         OffsetRect(gScreen, -left, -top); { _LocalToGlobal }
  1634.     ;
  1635.     gStripAddressMask := GetStripAddressMask;
  1636.  
  1637.     aMac2 := TestForColor(colorDepth);  { Feeds InitBigScreen. }
  1638.     InitBigScreen(FPDRsrc, sizeFont);   { Feeds wInitMenus. }
  1639.     mBarList := wInitMenus;        { ... not so usual.   }
  1640.     IF mBarList = NIL THEN
  1641.         ExitToShell;
  1642.     ;
  1643.     windowStorage := InitWindowStorage;
  1644.     IF windowStorage = NIL THEN
  1645.     BEGIN
  1646.         DisposHandle(Handle(mBarList));
  1647.         ExitToShell;
  1648.     END;
  1649.  
  1650.     Done := FALSE;                 { Init some other globals ... }
  1651.     InForeGround := TRUE;          { Assume UniFinder. }
  1652.     WNE := WNEisImplemented;
  1653.     Sleep := GetCaretTime;
  1654.     SetPt(offset, 0, 0);           { NO offset for the first window. }
  1655.     SetPt(deltaOffset, scrollWidth + frame, title + 3 * menuFrame);
  1656.     moreNew := TRUE;               { See "GetTLWindPortRect" }
  1657.     startBalloons := BalloonsOn;
  1658.     IF aMac2 THEN
  1659.     BEGIN
  1660.         currScreenDev := GetMainDevice;
  1661.         nextScreenDev := GetNextDevice(currScreenDev);
  1662.     END;
  1663.     SetUpMainMenus;
  1664.  
  1665.     System7Braggart;
  1666.  
  1667.     IF NOT DoNewWindow(mainWindowID, wMBARID, offset) THEN
  1668.     BEGIN                         { CanNOT find window resource. }
  1669.         DisposHandle(Handle(mBarList));
  1670.         HUnlock(Handle(windowStorage));
  1671.         DisposHandle(Handle(windowStorage));
  1672.         ExitToShell;
  1673.     END;
  1674.  
  1675.     MainEventLoop;
  1676.  
  1677.     ResetBalloons(startBalloons);
  1678.     ;
  1679.     PlaySound('Moof');
  1680.  
  1681.     ExitToShell;
  1682.  
  1683.  
  1684.  
  1685. END.   { Program }